package com.ruoyi.pack.service.impl;

import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.pack.domain.PackProject;
import com.ruoyi.pack.domain.PackProjectMaterial;
import com.ruoyi.pack.domain.PackProjectWarehouseOperation;
import com.ruoyi.pack.domain.dto.ProjectMaterialOperationDto;
import com.ruoyi.pack.domain.dto.ProjectWarehouseOperationDto;
import com.ruoyi.pack.domain.dto.OperationResultDto;
import com.ruoyi.pack.mapper.PackProjectMapper;
import com.ruoyi.pack.service.IPackProjectService;
import com.ruoyi.pack.service.IPackProjectMaterialService;
import com.ruoyi.pack.service.IPackProjectWarehouseOperationService;

/**
 * 项目Service业务层处理
 * 
 * @author ruoyi
 */
@Service
public class PackProjectServiceImpl implements IPackProjectService 
{
    private static final Logger log = LoggerFactory.getLogger(PackProjectServiceImpl.class);

    @Autowired
    private PackProjectMapper packProjectMapper;

    @Autowired
    private IPackProjectMaterialService packProjectMaterialService;

    @Autowired
    private IPackProjectWarehouseOperationService packProjectWarehouseOperationService;

    /**
     * 查询项目
     * 
     * @param projectId 项目主键
     * @return 项目
     */
    @Override
    public PackProject selectPackProjectByProjectId(Long projectId)
    {
        return packProjectMapper.selectPackProjectByProjectId(projectId);
    }

    /**
     * 查询项目列表
     * 
     * @param packProject 项目
     * @return 项目
     */
    @Override
    public List<PackProject> selectPackProjectList(PackProject packProject)
    {
        return packProjectMapper.selectPackProjectList(packProject);
    }

    /**
     * 查询项目列表（用于导出）
     * 
     * @param packProject 项目
     * @return 项目
     */
    @Override
    public List<PackProject> selectPackProjectListForExport(PackProject packProject)
    {
        return packProjectMapper.selectPackProjectListForExport(packProject);
    }

    /**
     * 新增项目
     * 
     * @param packProject 项目
     * @return 结果
     */
    @Override
    @Transactional
    public int insertPackProject(PackProject packProject)
    {
        // 校验项目编码唯一性
        if (checkProjectCodeUnique(packProject).equals("1"))
        {
            throw new ServiceException("新增项目'" + packProject.getProjectName() + "'失败，项目编码已存在");
        }
        
        packProject.setCreateTime(DateUtils.getNowDate());
        return packProjectMapper.insertPackProject(packProject);
    }

    /**
     * 修改项目
     * 
     * @param packProject 项目
     * @return 结果
     */
    @Override
    @Transactional
    public int updatePackProject(PackProject packProject)
    {
        // 校验项目编码唯一性
        if (checkProjectCodeUnique(packProject).equals("1"))
        {
            throw new ServiceException("修改项目'" + packProject.getProjectName() + "'失败，项目编码已存在");
        }
        
        packProject.setUpdateTime(DateUtils.getNowDate());
        return packProjectMapper.updatePackProject(packProject);
    }

    /**
     * 批量删除项目
     * 
     * @param projectIds 需要删除的项目主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deletePackProjectByProjectIds(Long[] projectIds)
    {
        for (Long projectId : projectIds)
        {
            deletePackProjectByProjectId(projectId);
        }
        return projectIds.length;
    }

    /**
     * 删除项目信息
     * 
     * @param projectId 项目主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deletePackProjectByProjectId(Long projectId)
    {
        // 删除项目关联的物料信息
        packProjectMaterialService.deletePackProjectMaterialByProjectId(projectId);
        
        // 删除项目关联的仓库操作权限
        packProjectWarehouseOperationService.deletePackProjectWarehouseOperationByProjectId(projectId);
        
        // 删除项目
        return packProjectMapper.deletePackProjectByProjectId(projectId);
    }

    /**
     * 校验项目编码是否唯一
     * 
     * @param packProject 项目信息
     * @return 结果
     */
    @Override
    public String checkProjectCodeUnique(PackProject packProject)
    {
        Long projectId = StringUtils.isNull(packProject.getProjectId()) ? -1L : packProject.getProjectId();
        PackProject info = packProjectMapper.checkProjectCodeUnique(packProject.getProjectCode());
        if (StringUtils.isNotNull(info) && info.getProjectId().longValue() != projectId.longValue())
        {
            return "1";
        }
        return "0";
    }

    /**
     * 查询公司下的所有项目
     * 
     * @param companyId 公司ID
     * @return 项目集合
     */
    @Override
    public List<PackProject> selectProjectsByCompanyId(Long companyId)
    {
        return packProjectMapper.selectProjectsByCompanyId(companyId);
    }

    /**
     * 查询用户权限范围内的项目
     * 
     * @param packProject 项目查询条件
     * @return 项目集合
     */
    @Override
    public List<PackProject> selectProjectsByDataScope(PackProject packProject)
    {
        return packProjectMapper.selectProjectsByDataScope(packProject);
    }

    /**
     * 导入项目数据
     * 
     * @param projectList 项目数据列表
     * @param isUpdateSupport 是否支持更新，如果已存在，则进行更新数据
     * @param operName 操作用户
     * @return 结果
     */
    @Override
    @Transactional
    public String importProject(List<PackProject> projectList, Boolean isUpdateSupport, String operName)
    {
        if (StringUtils.isNull(projectList) || projectList.size() == 0)
        {
            throw new ServiceException("导入项目数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        
        for (PackProject project : projectList)
        {
            try
            {
                // 验证是否存在这个项目
                PackProject p = packProjectMapper.checkProjectCodeUnique(project.getProjectCode());
                if (StringUtils.isNull(p))
                {
                    project.setCreateBy(operName);
                    this.insertPackProject(project);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、项目 " + project.getProjectName() + " 导入成功");
                }
                else if (isUpdateSupport)
                {
                    project.setProjectId(p.getProjectId());
                    project.setUpdateBy(operName);
                    this.updatePackProject(project);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、项目 " + project.getProjectName() + " 更新成功");
                }
                else
                {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、项目 " + project.getProjectName() + " 已存在");
                }
            }
            catch (Exception e)
            {
                failureNum++;
                String msg = "<br/>" + failureNum + "、项目 " + project.getProjectName() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        
        if (failureNum > 0)
        {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        }
        else
        {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    /**
     * 新增项目（带物料和仓库权限配置）
     * 
     * @param packProject 项目
     * @return 结果
     */
    @Override
    @Transactional
    public Map<String, Object> insertPackProjectWithDetails(PackProject packProject)
    {
        Map<String, Object> result = new HashMap<>();
        
        // 校验项目编码唯一性
        if (checkProjectCodeUnique(packProject).equals("1"))
        {
            throw new ServiceException("新增项目'" + packProject.getProjectName() + "'失败，项目编码已存在");
        }
        
        packProject.setCreateTime(DateUtils.getNowDate());
        int projectResult = packProjectMapper.insertPackProject(packProject);
        
        if (projectResult <= 0)
        {
            throw new ServiceException("新增项目失败");
        }
        
        result.put("projectId", packProject.getProjectId());
        result.put("projectCode", packProject.getProjectCode());
        
        // 处理物料配置
        List<Long> materialIds = new ArrayList<>();
        if (packProject.getMaterialList() != null && !packProject.getMaterialList().isEmpty())
        {
            for (PackProjectMaterial material : packProject.getMaterialList())
            {
                material.setProjectId(packProject.getProjectId());
                material.setCreateBy(packProject.getCreateBy());
                material.setCreateTime(DateUtils.getNowDate());
                packProjectMaterialService.insertPackProjectMaterial(material);
                materialIds.add(material.getProjectMaterialId());
            }
        }
        result.put("materialCount", materialIds.size());
        result.put("materialIds", materialIds);
        
        // 处理仓库权限配置
        List<Long> warehouseOperationIds = new ArrayList<>();
        if (packProject.getWarehouseOperationList() != null && !packProject.getWarehouseOperationList().isEmpty())
        {
            for (PackProjectWarehouseOperation operation : packProject.getWarehouseOperationList())
            {
                operation.setProjectId(packProject.getProjectId());
                operation.setCreateBy(packProject.getCreateBy());
                operation.setCreateTime(DateUtils.getNowDate());
                packProjectWarehouseOperationService.insertPackProjectWarehouseOperation(operation);
                warehouseOperationIds.add(operation.getProjectWarehouseId());
            }
        }
        result.put("warehouseOperationCount", warehouseOperationIds.size());
        result.put("warehouseOperationIds", warehouseOperationIds);
        
        return result;
    }

    /**
     * 修改项目（带物料和仓库权限操作）
     * 
     * @param packProject 项目
     * @return 结果
     */
    @Override
    @Transactional
    public Map<String, Object> updatePackProjectWithOperations(PackProject packProject)
    {
        Map<String, Object> result = new HashMap<>();
        
        // 校验项目编码唯一性
        if (checkProjectCodeUnique(packProject).equals("1"))
        {
            throw new ServiceException("修改项目'" + packProject.getProjectName() + "'失败，项目编码已存在");
        }
        
        packProject.setUpdateTime(DateUtils.getNowDate());
        int projectResult = packProjectMapper.updatePackProject(packProject);
        
        if (projectResult <= 0)
        {
            throw new ServiceException("修改项目失败");
        }
        
        result.put("projectId", packProject.getProjectId());
        
        // 处理物料操作
        List<OperationResultDto> materialOperationResults = new ArrayList<>();
        if (packProject.getMaterialOperations() != null && !packProject.getMaterialOperations().isEmpty())
        {
            for (ProjectMaterialOperationDto operation : packProject.getMaterialOperations())
            {
                OperationResultDto operationResult = new OperationResultDto();
                operationResult.setOperationType(operation.getOperationType());
                
                try
                {
                    switch (operation.getOperationType())
                    {
                        case "create":
                            PackProjectMaterial newMaterial = new PackProjectMaterial();
                            copyMaterialProperties(operation, newMaterial);
                            newMaterial.setProjectId(packProject.getProjectId());
                            newMaterial.setCreateBy(packProject.getUpdateBy());
                            newMaterial.setCreateTime(DateUtils.getNowDate());
                            packProjectMaterialService.insertPackProjectMaterial(newMaterial);
                            operationResult.setSuccess(true);
                            operationResult.setProjectMaterialId(newMaterial.getProjectMaterialId());
                            operationResult.setMaterialCode(newMaterial.getMaterialCode());
                            operationResult.setMessage("物料新增成功");
                            break;
                        case "update":
                            PackProjectMaterial updateMaterial = packProjectMaterialService.selectPackProjectMaterialByProjectMaterialId(operation.getProjectMaterialId());
                            if (updateMaterial == null)
                            {
                                throw new ServiceException("物料不存在");
                            }
                            copyMaterialProperties(operation, updateMaterial);
                            updateMaterial.setUpdateBy(packProject.getUpdateBy());
                            updateMaterial.setUpdateTime(DateUtils.getNowDate());
                            packProjectMaterialService.updatePackProjectMaterial(updateMaterial);
                            operationResult.setSuccess(true);
                            operationResult.setProjectMaterialId(updateMaterial.getProjectMaterialId());
                            operationResult.setMaterialCode(updateMaterial.getMaterialCode());
                            operationResult.setMessage("物料修改成功");
                            break;
                        case "delete":
                            packProjectMaterialService.deletePackProjectMaterialByProjectMaterialId(operation.getProjectMaterialId());
                            operationResult.setSuccess(true);
                            operationResult.setProjectMaterialId(operation.getProjectMaterialId());
                            operationResult.setMessage("物料删除成功");
                            break;
                        default:
                            throw new ServiceException("不支持的操作类型：" + operation.getOperationType());
                    }
                }
                catch (Exception e)
                {
                    operationResult.setSuccess(false);
                    operationResult.setMessage(e.getMessage());
                    log.error("物料操作失败", e);
                }
                
                materialOperationResults.add(operationResult);
            }
        }
        result.put("materialOperationResults", materialOperationResults);
        
        // 处理仓库权限操作
        List<OperationResultDto> warehouseOperationResults = new ArrayList<>();
        if (packProject.getWarehouseOperations() != null && !packProject.getWarehouseOperations().isEmpty())
        {
            for (ProjectWarehouseOperationDto operation : packProject.getWarehouseOperations())
            {
                OperationResultDto operationResult = new OperationResultDto();
                operationResult.setOperationType(operation.getOperationType());
                
                try
                {
                    switch (operation.getOperationType())
                    {
                        case "create":
                            PackProjectWarehouseOperation newOperation = new PackProjectWarehouseOperation();
                            copyWarehouseOperationProperties(operation, newOperation);
                            newOperation.setProjectId(packProject.getProjectId());
                            newOperation.setCreateBy(packProject.getUpdateBy());
                            newOperation.setCreateTime(DateUtils.getNowDate());
                            packProjectWarehouseOperationService.insertPackProjectWarehouseOperation(newOperation);
                            operationResult.setSuccess(true);
                            operationResult.setProjectWarehouseId(newOperation.getProjectWarehouseId());
                            operationResult.setWarehouseId(newOperation.getWarehouseId());
                            operationResult.setMessage("仓库权限新增成功");
                            break;
                        case "update":
                            PackProjectWarehouseOperation updateOperation = packProjectWarehouseOperationService.selectPackProjectWarehouseOperationByProjectWarehouseId(operation.getProjectWarehouseId());
                            if (updateOperation == null)
                            {
                                throw new ServiceException("仓库权限不存在");
                            }
                            copyWarehouseOperationProperties(operation, updateOperation);
                            updateOperation.setUpdateBy(packProject.getUpdateBy());
                            updateOperation.setUpdateTime(DateUtils.getNowDate());
                            packProjectWarehouseOperationService.updatePackProjectWarehouseOperation(updateOperation);
                            operationResult.setSuccess(true);
                            operationResult.setProjectWarehouseId(updateOperation.getProjectWarehouseId());
                            operationResult.setWarehouseId(updateOperation.getWarehouseId());
                            operationResult.setMessage("仓库权限修改成功");
                            break;
                        case "delete":
                            packProjectWarehouseOperationService.deletePackProjectWarehouseOperationByProjectWarehouseId(operation.getProjectWarehouseId());
                            operationResult.setSuccess(true);
                            operationResult.setProjectWarehouseId(operation.getProjectWarehouseId());
                            operationResult.setMessage("仓库权限删除成功");
                            break;
                        default:
                            throw new ServiceException("不支持的操作类型：" + operation.getOperationType());
                    }
                }
                catch (Exception e)
                {
                    operationResult.setSuccess(false);
                    operationResult.setMessage(e.getMessage());
                    log.error("仓库权限操作失败", e);
                }
                
                warehouseOperationResults.add(operationResult);
            }
        }
        result.put("warehouseOperationResults", warehouseOperationResults);
        
        return result;
    }

    /**
     * 删除项目信息（增强版，支持强制删除和数据清理）
     * 
     * @param projectId 项目主键
     * @param force 是否强制删除
     * @param cleanupData 是否清理相关数据
     * @return 结果
     */
    @Override
    @Transactional
    public Map<String, Object> deletePackProjectByProjectIdEnhanced(Long projectId, Boolean force, Boolean cleanupData)
    {
        Map<String, Object> result = new HashMap<>();
        
        PackProject project = packProjectMapper.selectPackProjectByProjectId(projectId);
        if (project == null)
        {
            throw new ServiceException("项目不存在");
        }
        
        result.put("projectId", projectId);
        result.put("projectCode", project.getProjectCode());
        
        // 检查是否有器具正在使用该项目
        // TODO: 这里需要查询器具表中current_project_id字段
        // int affectedContainerCount = containerService.countByCurrentProjectId(projectId);
        int affectedContainerCount = 0; // 临时设为0
        
        if (affectedContainerCount > 0 && !Boolean.TRUE.equals(force))
        {
            throw new ServiceException("项目下还有" + affectedContainerCount + "个器具正在使用，请设置force=true强制删除");
        }
        
        result.put("affectedContainerCount", affectedContainerCount);
        
        // 查询并删除项目物料
        List<PackProjectMaterial> materials = packProjectMaterialService.selectPackProjectMaterialByProjectId(projectId);
        List<Long> deletedMaterialIds = new ArrayList<>();
        for (PackProjectMaterial material : materials)
        {
            deletedMaterialIds.add(material.getProjectMaterialId());
        }
        packProjectMaterialService.deletePackProjectMaterialByProjectId(projectId);
        result.put("deletedMaterialIds", deletedMaterialIds);
        result.put("deletedMaterialCount", deletedMaterialIds.size());
        
        // 查询并删除项目仓库权限
        List<PackProjectWarehouseOperation> operations = packProjectWarehouseOperationService.selectPackProjectWarehouseOperationByProjectId(projectId);
        List<Long> deletedWarehouseOperationIds = new ArrayList<>();
        for (PackProjectWarehouseOperation operation : operations)
        {
            deletedWarehouseOperationIds.add(operation.getProjectWarehouseId());
        }
        packProjectWarehouseOperationService.deletePackProjectWarehouseOperationByProjectId(projectId);
        result.put("deletedWarehouseOperationIds", deletedWarehouseOperationIds);
        result.put("deletedWarehouseOperationCount", deletedWarehouseOperationIds.size());
        
        // 数据清理操作
        List<Map<String, Object>> cleanupOperations = new ArrayList<>();
        if (Boolean.TRUE.equals(cleanupData))
        {
            // 清理器具项目关联信息
            if (affectedContainerCount > 0)
            {
                Map<String, Object> cleanupOp = new HashMap<>();
                cleanupOp.put("operationType", "clear_container_project");
                cleanupOp.put("affectedCount", affectedContainerCount);
                cleanupOp.put("message", "清理器具项目关联信息");
                cleanupOperations.add(cleanupOp);
            }
            
            // 归档项目操作记录
            // TODO: 实际环境中需要实现相关的归档逻辑
            Map<String, Object> archiveOp = new HashMap<>();
            archiveOp.put("operationType", "archive_operation_logs");
            archiveOp.put("affectedCount", 0); // 暂时设为0
            archiveOp.put("message", "归档项目操作记录");
            cleanupOperations.add(archiveOp);
        }
        result.put("cleanupOperations", cleanupOperations);
        
        // 删除项目
        packProjectMapper.deletePackProjectByProjectId(projectId);
        
        return result;
    }

    /**
     * 获取项目详情（包含物料和仓库权限信息）
     * 
     * @param projectId 项目主键
     * @return 项目详情
     */
    @Override
    public PackProject selectPackProjectDetailsByProjectId(Long projectId)
    {
        PackProject project = packProjectMapper.selectPackProjectByProjectId(projectId);
        if (project != null)
        {
            // 查询项目物料列表
            List<PackProjectMaterial> materials = packProjectMaterialService.selectPackProjectMaterialByProjectId(projectId);
            project.setMaterialList(materials);
            
            // 查询项目仓库权限列表
            List<PackProjectWarehouseOperation> operations = packProjectWarehouseOperationService.selectPackProjectWarehouseOperationByProjectId(projectId);
            project.setWarehouseOperationList(operations);
            
            // 设置统计数量
            project.setMaterialCount(materials.size());
            project.setWarehouseCount(operations.size());
        }
        return project;
    }

    /**
     * 复制物料属性
     */
    private void copyMaterialProperties(ProjectMaterialOperationDto source, PackProjectMaterial target)
    {
        target.setMaterialCode(source.getMaterialCode());
        target.setMaterialName(source.getMaterialName());
        target.setContainerMaterialCode(source.getContainerMaterialCode());
        target.setContainerMaterialName(source.getContainerMaterialName());
        target.setLiningScheme(source.getLiningScheme());
        target.setCapacityCount(source.getCapacityCount());
        target.setVolume(source.getVolume());
        target.setWeight(source.getWeight());
        target.setGoodsValue(source.getGoodsValue());
    }

    /**
     * 复制仓库权限属性
     */
    private void copyWarehouseOperationProperties(ProjectWarehouseOperationDto source, PackProjectWarehouseOperation target)
    {
        target.setWarehouseId(source.getWarehouseId());
        target.setAllowFullInbound(source.getAllowFullInbound());
        target.setAllowFullOutbound(source.getAllowFullOutbound());
        target.setAllowEmptyInbound(source.getAllowEmptyInbound());
        target.setAllowEmptyOutbound(source.getAllowEmptyOutbound());
        target.setAllowPacking(source.getAllowPacking());
        target.setAllowUnpacking(source.getAllowUnpacking());
        target.setPackingTiming(source.getPackingTiming());
        target.setUnpackingTiming(source.getUnpackingTiming());
        target.setAllowFolding(source.getAllowFolding());
        target.setAllowCleaning(source.getAllowCleaning());
        target.setAllowRepair(source.getAllowRepair());
    }
} 